package ru.papergames.battleserver.telnet;

import javolution.text.TextBuilder;
import javolution.util.FastMap;
import org.apache.log4j.Logger;
import ru.common.util.Rnd;
import ru.papergames.Config;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author: atroshanin
 * Date: 22.04.2010
 * Time: 22:44:28
 */
public class BattleTelnetServer extends Thread {

    private ServerSocket statusServerSocket;

    private int uptime;
    private String statusPw;
    private String [] trustedHosts;

    private FastMap<Integer, BattleTelnetSession> sessions = new FastMap<Integer, BattleTelnetSession>().shared();

    private static final Logger logger = Logger.getLogger(BattleTelnetServer.class.getName());

    public void run() {
        try {
            int sessionCounter = 1;
            while (true) {
                try {
                    Socket connection = statusServerSocket.accept();
                    BattleTelnetSession session = new BattleTelnetSession(this, connection, uptime, statusPw, trustedHosts, sessionCounter++);
                    if (session.isStarted()) {
                        sessions.put(session.getSessionId(), session);
                    }
                    if (this.isInterrupted()) {
                        try {
                            statusServerSocket.close();
                        }
                        catch (IOException io) {
                            io.printStackTrace();
                        }
                        break;
                    }
                } catch (IOException e) {
                    if (this.isInterrupted()) {
                        try {
                            statusServerSocket.close();
                        } catch (IOException io) {
                            io.printStackTrace();
                        }
                        break;
                    }
                }
            }
        } finally {
            for(BattleTelnetSession session : sessions.values()) {
                session.interrupt();
            }
        }
    }

    void removeSession(int id) {
        sessions.remove(id);
    }

    public BattleTelnetServer() throws IOException {
        super("GameStatus");

        statusPw = Config.TELNET_PASSWORD;

        int _statusPort = Config.TELNET_PORT;
        if (statusPw == null) {
            logger.info("Server's Telnet Function Has No Password Defined!");
            logger.info("A Password Has Been Automaticly Created!");
            statusPw = rndPW(10);
            logger.info("Password Has Been Set To: " + statusPw);
        }
        logger.info("StatusServer Started! - Listening on Port: " + _statusPort);
        System.out.println("StatusServer Started! - Listening on Port: " + _statusPort);
        logger.info("Password Has Been Set To: " + statusPw);

        trustedHosts = Config.TELNET_LIST_OF_HOSTS.split(";");

        statusServerSocket = new ServerSocket(_statusPort);
        uptime = (int) System.currentTimeMillis();
    }

    private String rndPW(int length) {
        TextBuilder password = new TextBuilder();
        String lowerChar = "qwertyuiopasdfghjklzxcvbnm";
        String upperChar = "QWERTYUIOPASDFGHJKLZXCVBNM";
        String digits = "1234567890";
        for (int i = 0; i < length; i++) {
            int charSet = Rnd.nextInt(3);
            switch (charSet) {
                case 0:
                    password.append(lowerChar.charAt(Rnd.nextInt(lowerChar.length() - 1)));
                    break;
                case 1:
                    password.append(upperChar.charAt(Rnd.nextInt(upperChar.length() - 1)));
                    break;
                case 2:
                    password.append(digits.charAt(Rnd.nextInt(digits.length() - 1)));
                    break;
            }
        }
        return password.toString();
    }

    public void shutDown() {
        this.interrupt();
    }
}
